// 工具类
function Util(){}
Util.prototype.randomNum = function (minNum,maxNum){ 
    switch(arguments.length){ 
        case 1: 
            return parseInt(Math.random()*minNum+1,10); 
        case 2: 
            return parseInt(Math.random()*(maxNum-minNum+1)+minNum,10); 
        default: 
            return 0; 
    } 
}
// 蒙版类
function Masking(){
    this.masking = document.getElementById('masking');
    this.title = document.getElementById('masking-title');
    this.explain = document.getElementById('masking-explain');
    this.btn = document.getElementById('masking-btn');
}

// 游戏类
function Game(masking,snake,food){
    // 蒙版
    this.masking=masking;
    // 蛇
    this.snake=snake;
    // 食物
    this.food=food;
    // 状态 1初始化 2进行中 3暂停 4失败
    this.status=1;
    // 定时器
    this.time=null;
    // 分数
    this.score=0;
    // 难度
    this.lv=1;
    // 主界面
    this.main=document.getElementById('main');
    // 方向锁
    this.key=true;
}
// 蒙版渲染
Game.prototype.maskingRenderer=function(){
    var _self = this;
    switch(_self.status){
        case 1:
            _self.masking.title.innerHTML='准备开始';
            _self.masking.explain.innerHTML='点击下方开始按钮开始游戏';
            _self.masking.btn.innerHTML='开始游戏';
            _self.masking.masking.setAttribute('class','show');   
            _self.masking.btn.onclick=function(){
                _self.start();
            }
            break;
        case 2:
            _self.masking.masking.setAttribute('class','hide');    
            break;
        case 3:
            _self.masking.title.innerHTML='已暂停';
            _self.masking.explain.innerHTML='点击下方开始按钮，或点击空格开始游戏';
            _self.masking.btn.innerHTML='开始游戏';
            _self.masking.masking.setAttribute('class','show');
            _self.masking.btn.onclick=function(){
                _self.start();
            }
            break;
        case 4:
            _self.masking.title.innerHTML='游戏结束';
            _self.masking.explain.innerHTML='点击下方重新开始按钮，重新开始游戏';
            _self.masking.btn.innerHTML='重新开始';
            _self.masking.masking.setAttribute('class','show');
            _self.masking.btn.onclick=function(){
                _self.restart();
            }
            break;
    }
}
// 蛇渲染
Game.prototype.snakeRenderer=function(){
    var _self = this;
    // 清除旧的
    if(document.getElementById('snake')){
        _self.main.removeChild(document.getElementById('snake'));
    }
    var html = '';
    var div = document.createElement("div"); 
    div.id = 'snake';
    _self.snake.list.forEach(function(item){                        
        var left = item.x * 30 + 'px';
        var bottom = item.y * 30 + 'px';
        if(item.id==1){
            html+='<div id="snake-head" class="snake '+_self.snake.direction+'" style="left:'+left+';bottom:'+bottom+';">'+
                    '<div class="eye left-eye">'+
                        '<div class="eyeball"></div>'+
                    '</div>'+
                    '<div class="over-eye left-over-eye">×</div>'+
                    '<div class="eye right-eye">'+
                        '<div class="eyeball"></div>'+                         
                    '</div>'+
                    '<div class="over-eye right-over-eye">×</div>'+
                    '<div class="mouth"></div>'+
                '</div>';
        }else{
            html+='<div class="snake" style="left:'+left+';bottom:'+bottom+';"></div>';
        }                         
    })
    div.innerHTML = html;
    _self.main.appendChild(div);
}
// 食物渲染
Game.prototype.foodRenderer=function(){
    if(this.food.status==1){
        var div = document.createElement("div"); 
        div.id = 'food';
        div.style.left = this.food.x * 30 + 'px';
        div.style.bottom = this.food.y * 30 + 'px';
        div.appendChild(document.createElement("div"));
        main.appendChild(div);
    }else{
        main.removeChild(document.getElementById('food'));
    }
}
// 渲染分数和难度
Game.prototype.scoreLvRenderer=function(){
    document.getElementById('score').innerHTML = this.score;
    document.getElementById('lv').innerHTML = this.lv;
}
// 初始化
Game.prototype.init=function(){
    clearInterval(this.time);
    this.score = 0;
    this.lv = 1;
    this.time = null;
    this.main.innerHTML="";
    this.snake.init();
    this.food.init(this.snake.list);
    document.addEventListener("keydown",this.keydown.bind(this));
    this.maskingRenderer();
    this.snakeRenderer();
    this.foodRenderer();
    this.scoreLvRenderer();
}
// 重新开始
Game.prototype.restart=function(){
    this.status=2;
    this.init();
    this.start();
}
// 暂停
Game.prototype.pause=function(){
    if(this.status==2){
        clearInterval(this.time);
        this.time = null;
        this.status=3;
    }else if(this.status==3){
        this.start();
    }
    this.maskingRenderer();
}
// 开始游戏
Game.prototype.start=function(){
    this.status = 2;
    this.maskingRenderer();
    this.snakeMove();
}
// 监听键盘
Game.prototype.keydown=function(event){
    switch(event.keyCode){
        case 32:
            this.pause();
            break;
        case 38:
            if(this.snake.direction!='bottom'&&this.key){
                this.snake.direction = 'top';
                this.key = false;
            }
            break;
        case 40:
            if(this.snake.direction!='top'&&this.key){
                this.snake.direction = 'bottom';
                this.key = false;
            }
            break;
        case 37:
            if(this.snake.direction!='right'&&this.key){
                this.snake.direction = 'left';
                this.key = false;
            }
            break;
        case 39:
            if(this.snake.direction!='left'&&this.key){
                this.snake.direction = 'right';
                this.key = false;
            }
            break;
    }
}
// 获取速度
Game.prototype.getSpeed=function(){
    switch(this.lv){
        case 1:
            return 500;
        case 2:
            return 450;
        case 3:
            return 400;
        case 4:
            return 350;
        case 5:
            return 300;
        case 6:
            return 250;
        case 7:
            return 200;
        case 8:
            return 180;
        case 9:
            return 150;
        case 10:
            return 100;
        case 11:
            return 50;
    }
}
// 积分/难度
Game.prototype.getScore=function(){
    this.score += this.lv * 50;
    if(this.score<100){
        this.lv = 1;
        clearInterval(this.time);
        this.snakeMove();
    }
    if(this.score>=100&&this.score<400){
        this.lv = 2;
        clearInterval(this.time);
        this.snakeMove();
    }
    if(this.score>=400&&this.score<1000){
        this.lv = 3;
        clearInterval(this.time);
        this.snakeMove();
    }
    if(this.score>=1000&&this.score<2000){
        this.lv = 4;
        clearInterval(this.time);
        this.snakeMove();
    }
    if(this.score>=2000&&this.score<3500){
        this.lv = 5;
        clearInterval(this.time);
        this.snakeMove();
    }
    if(this.score>=3500&&this.score<=5600){
        this.lv = 6;
        clearInterval(this.time);
        this.snakeMove();
    }
    if(this.score>5600&&this.score<=8400){
        this.lv = 7;
        clearInterval(this.time);
        this.snakeMove();
    }
    if(this.score>8400&&this.score<=12000){
        this.lv = 8;
        clearInterval(this.time);
        this.snakeMove();
    }
    if(this.score>12000&&this.score<=16500){
        this.lv = 9;
        clearInterval(this.time);
        this.snakeMove();
    }
    if(this.score>16500&&this.score<=22000){
        this.lv = 10;
        clearInterval(this.time);
        this.snakeMove();
    }
    if(this.score>22000){
        this.lv = 11;
        clearInterval(this.time);
        this.snakeMove();
    }
    this.scoreLvRenderer();
}
// 蛇移动
Game.prototype.snakeMove=function(){
    var _self = this;
    _self.time = setInterval(function(){       
        _self.snake.move();   
        _self.key = true;
        // 判断事件
        if(!_self.judgeEvent()){
            clearInterval(_self.time);
            return false;
        }
        _self.snakeRenderer();    
    },_self.getSpeed());
}
// 判断事件
Game.prototype.judgeEvent=function(){
    var head = this.snake.list[0];
    // 判断是否咬到自己
    for(var i=1;i<this.snake.list.length;i++){
        var item = this.snake.list[i];
        if(head.x==item.x&&head.y==item.y){
            document.getElementById('snake-head').setAttribute('class','snake '+this.snake.direction+' over'); 
            this.status = 4;
            this.maskingRenderer();              
            return false;
        }
    }
    // 判断吃没吃到食物
    if(head.x==this.food.x&&head.y==this.food.y){
        this.food.eat();
        this.foodRenderer();
        this.snake.eat();            
        this.food.new(this.snake.list);
        this.foodRenderer();
        this.getScore();
    }
    return true;
}

// 蛇类
function Snake(util){
    // 工具类
    this.util=util;
    // 索引
    this.id=1;
    // 蛇身
    this.list=[];
    // 方向
    this.direction='';
}
// 初始化蛇身
Snake.prototype.init=function(){
    this.list=[];
    // 初始化蛇头
    this.id = 1;
    this.list.push({
        id:this.id,
        x:this.util.randomNum(1,14),
        y:this.util.randomNum(1,14),
        oldX:0,
        oldY:0 
    });
    this.id++;
    var head = this.list[0];
    // 随机方向并加入第一段蛇身 1上 2下 3左 4右
    switch(this.util.randomNum(1,4)){
        case 1:
            this.direction = 'top';
            this.list.push({
                id:this.id,
                x:head.x,
                y:head.y-1,
                oldX:0,
                oldY:0 
            });
            break;
        case 2:
            this.direction = 'bottom';
            this.list.push({
                id:this.id,
                x:head.x,
                y:head.y+1,
                oldX:0,
                oldY:0 
            });
            break;
        case 3:
            this.direction = 'left';
            this.list.push({
                id:this.id,
                x:head.x+1,
                y:head.y,
                oldX:0,
                oldY:0 
            });
            break;
        case 4:
            this.direction = 'right';
            this.list.push({
                id:this.id,
                x:head.x-1,
                y:head.y,
                oldX:0,
                oldY:0 
            });
            break;
    }
}
// 吃食物
Snake.prototype.eat=function(){
    // 判断如果只剩一格占满屏幕就不增长了
    if(this.list.length<255){
        // 蛇尾
        var end = this.list[this.list.length-1];
        this.id++;
        this.list.push({
            id:this.id,
            x:end.oldX,
            y:end.oldY,
            oldX:0,
            oldY:0 
        });
    }
}
// 移动方法
Snake.prototype.move=function(){       
    // 蛇头
    var head = this.list[0];
    head.oldX = head.x;
    head.oldY = head.y;
    switch(this.direction){
        case 'top':
            if(head.y==15){
                head.y=0;
            }else{
                head.y++;
            }             
            break;
        case 'bottom':
            if(head.y==0){
                head.y=15;
            }else{
                head.y--;
            }    
            break;
        case 'left':
            if(head.x==0){
                head.x=15;
            }else{
                head.x--;
            }    
            break;
        case 'right':
            if(head.x==15){
                head.x=0;
            }else{
                head.x++;
            }    
            break;
    }
    
    for(var i=1;i<this.list.length;i++){
        var item = this.list[i];
        item.oldX = item.x;
        item.oldY = item.y;
        item.x = this.list[i-1].oldX;
        item.y = this.list[i-1].oldY;
    }
}

// 食物类
function Food(util){
    // 工具类
    this.util=util;
    // 索引
    this.id=1;
    // 横坐标
    this.x=0;
    // 纵坐标
    this.y=0;
    // 状态 0 消失 1 出现
    this.status=0;
}
// 初始化食物
Food.prototype.init=function(snakeList){
    this.id=1;
    this.x=0;
    this.y=0;
    this.new(snakeList);
}
// 被吃掉
Food.prototype.eat=function(){
    this.status=0;
}
// 新食物
Food.prototype.new=function(snakeList){
    // 获取没有蛇的格
    var noSnakeList = [];
    for(var i=0;i<16;i++){
        for(var j=0;j<16;j++){
            let key = true;
            snakeList.forEach(function(item){
                if(i==item.x&&j==item.y){
                    key = false;
                    return false;
                }
            })
            if(key){
                noSnakeList.push({x:i,y:j});
            }
        }
    }          
    // 从中随机选出一个格
    var position = noSnakeList[this.util.randomNum(0,noSnakeList.length-1)];
    this.x = position.x;
    this.y = position.y;
    this.status = 1;
}
var util = new Util();
var masking = new Masking();
var snake = new Snake(util);
var food = new Food(util);
var game = new Game(masking,snake,food);
// 初始化游戏
game.init();